/*
 * Copyright (c) 2020 - present, Inspur Genersoft Co., Ltd.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package io.iec.edp.caf.tenancy.core.service;


import io.iec.edp.caf.tenancy.api.entity.DbConnectionInfo;
import io.iec.edp.caf.tenancy.api.service.DbConnectionService;
import io.iec.edp.caf.tenancy.core.TenantCache;
import io.iec.edp.caf.tenancy.core.repository.DbConnectionRepository;
import io.iec.edp.caf.tenancy.core.repository.SuDbMappingRepository;
import io.iec.edp.caf.tenancy.core.utils.DataValidator;

import lombok.var;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;

/**
 * DbConnectionManager$
 *
 * @author Hey Law
 * @create 2019年8月21日19:12:23$
 */
public class DbConnectionManager implements DbConnectionService {

    private final DbConnectionRepository repository;

//    private SuDbMappingRepository mappingRepository;

    private final TenantCache tenantCache;


    private final ConcurrentHashMap<String, DbConnectionInfo> connInfos = new ConcurrentHashMap<>();

    public DbConnectionManager(DbConnectionRepository repository, SuDbMappingRepository mappingRepository, TenantCache tenantCache)
    {
        this.repository = repository;
//        this.mappingRepository = mappingRepository;
        this.tenantCache = tenantCache;
    }

    /**
     * 根据标识获取所有连接信息
     *
     * @param id 连接标识
     * @return
    */
    public DbConnectionInfo get(String id)
    {
        DataValidator.checkForEmptyString(id, "id");
        String cacheKey = this.getCacheKey(id);

        //启用二级缓存
        return connInfos.computeIfAbsent(cacheKey, s ->
            {
                DbConnectionInfo info = tenantCache.get(cacheKey, DbConnectionInfo.class);

                if (info == null)
                {
                    info = this.repository.findById(id).orElse(null);
                    if (info != null)
                    {
                        //解密连接字符串，感觉也不太合适，暂时先放这儿吧
                        tenantCache.set(cacheKey, info);
                    }
                }

                return info;
            });
    }



    /**
     * 根据应用标识获取所有连接信息
     *
     * @param appInstanceId 应用标识
     * @return
    */
//    @Transactional(propagation = Propagation.REQUIRED,readOnly=true)
    public List<DbConnectionInfo> getByAppInstanceId(String appInstanceId)
    {
        DataValidator.checkForEmptyString(appInstanceId, "appInstanceId");

        var dbConns = this.repository.findByAppInstanceId(appInstanceId);
        return dbConns;
    }

    /**
     * 添加
     *
     * @param infos 数据库连接信息
     * @return
    */
    public void add(List<DbConnectionInfo> infos)
    {
        DataValidator.checkForNullReference(infos, "List<DbConnection>");
        List<DbConnectionInfo> list = new ArrayList<>();
        //每个连接字符串加密处理
        infos.forEach(x ->
                list.add(x)
        );
        this.repository.saveAll(infos);
    }

    /// <summary>
    /// 更新租户信息
    /// </summary>
    /**
     * 更新租户信息
     *
     * @param infos 数据库连接信息
     * @return
    */
    public boolean update(List<DbConnectionInfo> infos)
    {
        DataValidator.checkForNullReference(infos, "List<DbConnection>");
        this.repository.saveAll(infos);

        //先删除，再获取最新的并缓存
        for(var s : infos)
        {
            String cacheKey = this.getCacheKey(s.getId());
            tenantCache.remove(cacheKey);
        }

        return true;
    }

    /**
     * 删除
     *
     * @param appInstanceId 应用实例编号
     * @return
     * @Date: 2019/8/22
    */
    public boolean removeByAppInstanceId(String appInstanceId)
    {
        DataValidator.checkForEmptyString(appInstanceId, "appInstanceId");

        var infos = this.getByAppInstanceId(appInstanceId);
        if (infos != null && infos.size() > 0)
        {
            this.repository.deleteAll(infos);
            for (var item : infos)
            {
                String cacheKey = this.getCacheKey(item.getId());
                tenantCache.remove(cacheKey);
            }
        }

        return true;
    }

    /**
     * 根据租户标识获取缓存key
     *
     * @param dbConnectionId dbConnectionId
     * @return
     * @Date: 2019/8/21
     */
    private String getCacheKey(String dbConnectionId)
    {
        return String.format("DB_%s", dbConnectionId);
    }

}
